package ygo

import (
	"fmt"
	"dumpwave"
)

func decode(
		instruction       chan uint32,
		cop0Decode        chan uint32,
		decodeAlu         chan DEAL,
		decodeCop0        chan DECO,
		decodeRegister    chan DERE,
		decodeDmux        chan DEDM,
		decodeMux         chan DEMU,
		decodePC          chan DEPC,
		aluDecode_branch  chan uint32,
		decodeYam         chan uint32) {

	var (
		OpCode uint32
		rd uint32
		rt uint32
		rs uint32
		base uint32
		offset uint32
		instr_index uint32
		var_decode uint32
		stateNextDecode uint32
		stateDecode uint32
		cp0bds uint32

		var_branch_monitor uint32
		end uint32
	)

	stateNextDecode = STATE_OTHERS

	for {
		stateDecode = stateNextDecode

		var_instruction :=<- instruction
		fmt.Printf("[DECODE] Instruction <-- YAM: 0x%x\n",var_instruction)

		var_command :=<- cop0Decode
		switch var_command {
			case INTERRUPTION:
				fmt.Println("[DECODE] command <-- COP0 (INTERRUPTION)")

				var_decode = NO
				stateNextDecode = STATE_NULLIFY_NEXT_2
				fmt.Println("[DECODE] DECO --> COPO (cmd: NOTHING, cp0bds: 0)")
				decodeCop0 <- DECO{CP0_COMMAND: NOTHING, CP0_BDS: 0}

				switch stateDecode {
					case STATE_BRANCH_LIKELY_SENT:
					{
						var_branch_monitor =<- aluDecode_branch
						fmt.Printf("[DECODE] DEPC --> PC (cmd: PC_INTERRUPT, immediate: 0x0, offset: 0x0 buffers: %d)\n",0)
						decodePC <- DEPC{PC_COMMAND:PC_INTERRUPT, PC_IMMEDIATE: 0, PC_OFFSET: 0, PC_BUFFERS: 0}
					}
					case STATE_BRANCH_SENT:
					{
						var_branch_monitor =<- aluDecode_branch
						fmt.Printf("[DECODE] DEPC --> PC (cmd: PC_INTERRUPT, immediate: 0x0, offset: 0x0 buffers: %d)\n",1)
						decodePC <- DEPC{PC_COMMAND:PC_INTERRUPT, PC_IMMEDIATE: 0, PC_OFFSET: 0, PC_BUFFERS: 1}
					}
					case STATE_NULLIFY_NEXT:
					{
						//current instruction is ignored, return address is next instruction,
						//i.e. instruction in delay slot
						fmt.Printf("[DECODE] DEPC --> PC (cmd: PC_INTERRUPT_IN_DS, immediate: 0x0, offset: 0x0 buffers: %d)\n",0)
						decodePC <- DEPC{PC_COMMAND:PC_INTERRUPT_IN_DS, PC_IMMEDIATE: 0, PC_OFFSET: 0, PC_BUFFERS: 0}
					}
					case STATE_NULLIFY_NEXT_2:
					{
						//current and next instruction are ignored, return address is after next instruction,
						//i.e. instruction in memory fetch
						fmt.Printf("[DECODE] DEPC --> PC (cmd: PC_INTERRUPT_IN_MEMORY, immediate: 0x0, offset: 0x0 buffers: %d)\n",0)
						decodePC <- DEPC{PC_COMMAND: PC_INTERRUPT_IN_MEMORY, PC_IMMEDIATE: 0, PC_OFFSET: 0, PC_BUFFERS: 0}
					}
					case STATE_DELAY_SLOT_SENT:
					{
						var_branch_monitor =<- aluDecode_branch
						if var_branch_monitor==1 {
							//branch was taken.. correct return address is actual intruction in memory fetch
							//decode and delay slot instruction are ignored!
							fmt.Printf("[DECODE] DEPC --> PC (cmd: PC_INTERRUPT_IN_MEMORY, immediate: 0x0, offset: 0x0 buffers: %d)\n",0)
							decodePC <- DEPC{PC_COMMAND:PC_INTERRUPT_IN_MEMORY, PC_IMMEDIATE: 0, PC_OFFSET: 0, PC_BUFFERS: 0}
						} else {
							//branch was NOT taken, so current instruction can not be ignored, so 
							//the current instruction in decode is the return address
							fmt.Printf("[DECODE] DEPC --> PC (cmd: PC_INTERRUPT, immediate: 0x0, offset: 0x0 buffers: %d)\n",0)
							decodePC <- DEPC{PC_COMMAND:PC_INTERRUPT, PC_IMMEDIATE: 0, PC_OFFSET: 0, PC_BUFFERS: 0}
						}
					}
					default:
				}

			case CORE_INTERRUPTION:
				fmt.Println("[DECODE] command <-- COP0 (CORE_INTERRUPTION)")

				var_decode = NO
				stateNextDecode = STATE_NULLIFY_NEXT_2
				fmt.Println("[DECODE] DECO --> COPO (cmd: NOTHING, cp0bds: 0)")
				decodeCop0 <- DECO{CP0_COMMAND: NOTHING, CP0_BDS: 0}

				switch stateDecode {
					case STATE_BRANCH_SENT :
					{
						fmt.Printf("[DECODE] DEPC --> PC (cmd: PC_INTERRUPT_IN_EXEC, immediate: 0x0, offset: 0x0 buffers: %d)\n",1)
						decodePC <- DEPC{PC_COMMAND: PC_INTERRUPT_IN_EXEC, PC_IMMEDIATE: 0, PC_OFFSET: 0, PC_BUFFERS: 1}
						var_branch_monitor =<- aluDecode_branch
					}
					case STATE_BRANCH_LIKELY_SENT:
					case STATE_DELAY_SLOT_SENT:
					{
						fmt.Printf("[DECODE] DEPC --> PC (cmd: PC_INTERRUPT_IN_EXEC, immediate: 0x0, offset: 0x0 buffers: %d)\n",0)
						decodePC <- DEPC{PC_COMMAND:PC_INTERRUPT_IN_EXEC, PC_IMMEDIATE: 0, PC_OFFSET: 0, PC_BUFFERS: 0}
						var_branch_monitor =<- aluDecode_branch
					}
					default:
					{
						fmt.Printf("[DECODE] DEPC --> PC (cmd: PC_INTERRUPT_IN_EXEC, immediate: 0x0, offset: 0x0 buffers: %d)\n",0)
						decodePC <- DEPC{PC_COMMAND:PC_INTERRUPT_IN_EXEC, PC_IMMEDIATE: 0, PC_OFFSET: 0, PC_BUFFERS: 0}
					}
				}

			case RETURN:
				fmt.Println("[DECODE] command <-- COP0 (RETURN)")

				var_decode = NO
				stateNextDecode = STATE_NULLIFY_NEXT_2
				fmt.Println("[DECODE] DECO --> COPO (cmd: NOTHING, cp0bds: 0)")
				decodeCop0 <-DECO{CP0_COMMAND: NOTHING, CP0_BDS: 0}
				
				fmt.Printf("[DECODE] DEPC --> PC (cmd: PC_RETURN, immediate: 0x0, offset: 0x0 buffers: 0)\n")
				decodePC <- DEPC{PC_COMMAND: PC_RETURN, PC_IMMEDIATE: 0, PC_OFFSET: 0, PC_BUFFERS: 0}

			case CONTINUE:
				fmt.Println("[DECODE] command <-- COP0 (CONTINUE)")

				switch stateDecode{
					case STATE_BRANCH_LIKELY_SENT:
					{
						var_branch_monitor =<- aluDecode_branch
						if var_branch_monitor == 0 {
							var_decode = NO
							stateNextDecode = STATE_OTHERS
							fmt.Println("[DECODE] DECO --> COPO (cmd: NOTHING, cp0bds: 0)")
							decodeCop0 <-DECO{CP0_COMMAND: NOTHING, CP0_BDS: 0}
							fmt.Printf("[DECODE] DEPC --> PC (cmd: PC_NEXT, immediate: 0x0, offset: 0x0 buffers: 0)\n")
							decodePC <- DEPC{PC_COMMAND: PC_NEXT, PC_IMMEDIATE: 0, PC_OFFSET: 0, PC_BUFFERS: 0}
						} else {
							var_decode = IGNORE_JUMPS
							stateNextDecode = STATE_NULLIFY_NEXT
							//indicates decode to ignore jumps = DELAY SLOT and do not calculate
							fmt.Printf("[DECODE] DEPC --> PC (cmd: PC_NEXT, immediate: 0x0, offset: 0x0 buffers: 0)\n")
							decodePC <- DEPC{PC_COMMAND: PC_NEXT, PC_IMMEDIATE: 0, PC_OFFSET: 0, PC_BUFFERS: 0}
						}
					}
					case STATE_BRANCH_SENT:
					{
						var_decode = IGNORE_JUMPS
						stateNextDecode = STATE_DELAY_SLOT_SENT
						fmt.Printf("[DECODE] DEPC --> PC (cmd: PC_DELAYED_BRANCH, immediate: 0x0, offset: 0x0 buffers: 0)\n")
						decodePC <- DEPC{PC_COMMAND: PC_DELAYED_BRANCH, PC_IMMEDIATE: 0, PC_OFFSET: 0, PC_BUFFERS: 0}
					}	
					case STATE_NULLIFY_NEXT:
					{
						fmt.Println("[DECODE] stateDecode = STATE_NULLIFY_NEXT")
						var_decode = NO
						stateNextDecode = STATE_OTHERS
						fmt.Println("[DECODE] DECO --> COPO (cmd: NOTHING, cp0bds: 0)")
						decodeCop0 <-DECO{CP0_COMMAND: NOTHING, CP0_BDS: 0}
						fmt.Printf("[DECODE] DEPC --> PC (cmd: PC_NEXT, immediate: 0x0, offset: 0x0 buffers: 0)\n")
						decodePC <- DEPC{PC_COMMAND: PC_NEXT, PC_IMMEDIATE: 0, PC_OFFSET: 0, PC_BUFFERS: 0}
					}	
					case STATE_NULLIFY_NEXT_2:
					{
						var_decode = NO
						stateNextDecode = STATE_NULLIFY_NEXT
						fmt.Println("[DECODE] DECO --> COPO (cmd: NOTHING, cp0bds: 0)")
						decodeCop0 <-DECO{CP0_COMMAND: NOTHING, CP0_BDS: 0}
						fmt.Println("[DECODE] DEPC --> PC (cmd: PC_NEXT, immediate: 0x0, offset: 0x0 buffers: 0)")
						decodePC <- DEPC{PC_COMMAND: PC_NEXT, PC_IMMEDIATE: 0, PC_OFFSET: 0, PC_BUFFERS: 0}
					}	
					case STATE_NULLIFY_SECOND:
					{  
						fmt.Println("[DECODE] stateDecode = STATE_NULLIFY_SECOND")
						var_decode = IGNORE_JUMPS
						fmt.Println("[DECODE] stateNextDecode = STATE_NULLIFY_NEXT")
						stateNextDecode = STATE_NULLIFY_NEXT
						fmt.Printf("[DECODE] DEPC --> PC (cmd: PC_NEXT, immediate: 0x0, offset: 0x0 buffers: 0)\n")
						decodePC <- DEPC{PC_COMMAND: PC_NEXT, PC_IMMEDIATE: 0, PC_OFFSET: 0, PC_BUFFERS: 0}
					}	
					case STATE_DELAY_SLOT_SENT:
					{
						var_branch_monitor =<- aluDecode_branch
						if var_branch_monitor==1 {
							//branch is taken (nullify current and next)
							var_decode = NO
							stateNextDecode = STATE_NULLIFY_NEXT
							fmt.Println("[DECODE] DECO --> COPO (cmd: NOTHING, cp0bds: 0)")
							decodeCop0 <-DECO{CP0_COMMAND: NOTHING, CP0_BDS: 0}
							fmt.Printf("[DECODE] DEPC --> PC (cmd: PC_NEXT, immediate: 0x0, offset: 0x0 buffers: 0)\n")
							decodePC <- DEPC{PC_COMMAND: PC_NEXT, PC_IMMEDIATE: 0, PC_OFFSET: 0, PC_BUFFERS: 0}
						} else {
							//branch is not taken (continue executing)
							var_decode = YES
						}
					}	
					default:
						fmt.Println("[DECODE] stateDecode = OTHERS")
						var_decode = YES
				}
		}

		if var_decode != NO {
// 			var_instruction :=<-instruction
// 			dumpwave.Wave(0,"req_ack_INST")
// 			dumpwave.Wave(1,"ack_INST")
// 			fmt.Printf("[DECODE] Instruction <-- YAM: 0x%x\n",var_instruction)

			if var_instruction == 0 {
				decodeYam <- end
			} else {
				OpCode = var_instruction >>26 //recebe os bits de 31 a 26 (registrador opcode)
				fmt.Println("[DECODE] stateDecode =",stateDecode)
				//var_decode = YES
				switch OpCode {
					case ADDI:
						rt = (var_instruction & 0x1F0000)>>16
						rs = (var_instruction & 0x3E00000)>>21
						imme := (var_instruction & 0xFFFF)
						if var_decode == YES{
							stateNextDecode = STATE_OTHERS
							cp0bds = 0
							fmt.Println("[DECODE] stateDecode = YES")
						} else{
							cp0bds = 1
						}

						fmt.Println("[DECODE] DECO --> COPO (cmd: WAIT_EXCEPTION)")
						decodeCop0 <-DECO{CP0_COMMAND: WAIT_EXCEPTION, CP0_BDS: cp0bds}

						fmt.Printf("[DECODE] DEAL --> ALU (cmd: ADD, immediate: 0x%x)", imme)
						decodeAlu <- DEAL{CMD: ADD, IMMEDIATE: imme}

						fmt.Printf("[DECODE] DERE --> REGISTER (cmd: RRS_RRT_WRD, rs: 0x%x, rt: 0x%x, rd: 0x%x)\n",rs,rt,rd)
						decodeRegister <-DERE{RF_COMMAND:RRS_WRT, RS:rs, RT:rt, RD:0}

						fmt.Println("[DECODE] DEDM --> DMUX (cmd: RRS_RRT_WRD, unit: ALU)")
						decodeDmux <- DEDM{DMUX_COMMAND:RRS_WRT, DMUX_UNIT:ALU}

						fmt.Println("[DECODE] DEMU --> MUX (cmd: RRS_RRT_WRD, unit: ALU)")
						decodeMux <- DEMU{MUX_COMMAND:RRS_RRT_WRD, MUX_UNIT:ALU}
						
						if var_decode == YES{
							fmt.Printf("[DECODE] DEPC --> PC (cmd: PC_NEXT, immediate: 0x%x, offset: 0x%x buffers: 0)\n",instr_index,offset)
							decodePC <- DEPC{PC_COMMAND:PC_NEXT, PC_IMMEDIATE: 0, PC_OFFSET: 0, PC_BUFFERS: 0}
						}
						
					case SPECIAL:
						fmt.Println("[DECODE] tag SPECIAL")
						OpCode = (var_instruction & 0x3F)
						switch OpCode {
						case ADD:
								fmt.Println("[DECODE] tag ADD")
								rd = (var_instruction & 0xF800)>>11
								rt = (var_instruction & 0x1F0000)>>16
								rs = (var_instruction & 0x3E00000)>>21

								// status do decode
								if var_decode == YES{
									cp0bds = 0
									fmt.Println("[DECODE] stateDecode = YES")
								} else{
									cp0bds = 1
								}

								fmt.Println("[DECODE] DECO --> COPO (cmd: WAIT_EXCEPTION)")
								decodeCop0 <-DECO{CP0_COMMAND: WAIT_EXCEPTION, CP0_BDS: cp0bds}

								fmt.Printf("[DECODE] DEAL --> ALU (cmd: ADD, immediate: 0)")
								decodeAlu <- DEAL{CMD: ADD, IMMEDIATE: 0}

								fmt.Printf("[DECODE] DERE --> REGISTER (cmd: RRS_RRT_WRD, rs: 0x%x, rt: 0x%x, rd: 0x%x)\n",rs,rt,rd)
								decodeRegister <-DERE{RF_COMMAND:RRS_RRT_WRD, RS:rs, RT:rt, RD:rd}

								fmt.Println("[DECODE] DEDM --> DMUX (cmd: RRS_RRT_WRD, unit: ALU)")
								decodeDmux <- DEDM{DMUX_COMMAND:RRS_RRT_WRD, DMUX_UNIT:ALU}

								fmt.Println("[DECODE] DEMU --> MUX (cmd: RRS_RRT_WRD, unit: ALU)")
								decodeMux <- DEMU{MUX_COMMAND:RRS_RRT_WRD, MUX_UNIT:ALU}
								
								if var_decode == YES{
									stateNextDecode = STATE_OTHERS
									//pc_command <- PC_NEXT
									fmt.Printf("[DECODE] DEPC --> PC (cmd: PC_NEXT, immediate: 0x%x, offset: 0x%x buffers: 0)\n",instr_index,offset)
									decodePC <- DEPC{PC_COMMAND:PC_NEXT, PC_IMMEDIATE: 0, PC_OFFSET: 0, PC_BUFFERS: 0}
								}

							case SUB:
								fmt.Println("[DECODE] tag SUB")
								rd = (var_instruction & 0xF800)>>11
								rt = (var_instruction & 0x1F0000)>>16
								rs = (var_instruction & 0x3E00000)>>21
								// status do decode
								if var_decode == YES{
									cp0bds = 0
									fmt.Println("[DECODE] stateDecode = YES")
								} else{
									cp0bds = 1
								}

								fmt.Println("[DECODE] DECO --> COPO (cmd: WAIT_EXCEPTION)")
								decodeCop0 <-DECO{CP0_COMMAND: WAIT_EXCEPTION, CP0_BDS: cp0bds}

								fmt.Println("[DECODE] DEAL --> ALU (cmd: SUB, immediate: 0)")
								decodeAlu <- DEAL{CMD: SUB, IMMEDIATE: 0}

								fmt.Printf("[DECODE] DERE --> REGISTER (cmd: RRS_RRT_WRD, rs: 0x%x, rt: 0x%x, rd: 0x%x)\n",rs,rt,rd)
								decodeRegister <-DERE{RF_COMMAND:RRS_RRT_WRD, RS:rs, RT:rt, RD:rd}

								fmt.Println("[DECODE] DEDM --> DMUX (cmd: RRS_RRT_WRD, unit: ALU)")
								decodeDmux <- DEDM{DMUX_COMMAND:RRS_RRT_WRD, DMUX_UNIT:ALU}

								fmt.Println("[DECODE] DEMU --> MUX (cmd: RRS_RRT_WRD, unit: ALU)")
								decodeMux <- DEMU{MUX_COMMAND:RRS_RRT_WRD, MUX_UNIT:ALU}
								
								if var_decode == YES{
									stateNextDecode = STATE_OTHERS
									fmt.Printf("[DECODE] DEPC --> PC (cmd: PC_NEXT, immediate: 0x%x, offset: 0x%x, buffers: 0)\n",instr_index,offset)
									decodePC <- DEPC{PC_COMMAND:PC_NEXT, PC_IMMEDIATE: 0, PC_OFFSET: 0, PC_BUFFERS: 0}
								}

							case AND:
								fmt.Println("[DECODE] tag AND")
								rd = (var_instruction & 0xF800)>>11
								rt = (var_instruction & 0x1F0000)>>16
								rs = (var_instruction & 0x3E00000)>>21
								// status do decode
								if var_decode == YES{
									cp0bds = 0
									fmt.Println("[DECODE] stateDecode = YES")
								} else{
									cp0bds = 1
								}

								fmt.Println("[DECODE] DECO --> COPO (cmd: WAIT_EXCEPTION)")
								decodeCop0 <-DECO{CP0_COMMAND: WAIT_EXCEPTION, CP0_BDS: cp0bds}
								
								fmt.Println("[DECODE] DEAL --> ALU (cmd: AND, immediate: 0)")
								decodeAlu <- DEAL{CMD: AND, IMMEDIATE: 0}

								fmt.Printf("[DECODE] DERE --> REGISTER (cmd: RRS_RRT_WRD, rs: 0x%x, rt: 0x%x, rd: 0x%x)\n",rs,rt,rd)
								decodeRegister <-DERE{RF_COMMAND:RRS_RRT_WRD, RS:rs, RT:rt, RD:rd}

								fmt.Println("[DECODE] DEDM --> DMUX (cmd: RRS_RRT_WRD, unit: ALU)")
								decodeDmux <- DEDM{DMUX_COMMAND:RRS_RRT_WRD, DMUX_UNIT:ALU}

								fmt.Println("[DECODE] DEMU --> MUX (cmd: RRS_RRT_WRD, unit: ALU)")
								decodeMux <- DEMU{MUX_COMMAND:RRS_RRT_WRD, MUX_UNIT:ALU}
								
								if var_decode == YES{
									stateNextDecode = STATE_OTHERS
									fmt.Printf("[DECODE] DEPC --> PC (cmd: PC_NEXT, immediate: 0x%x, offset: 0x%x, buffers: 0)\n",instr_index,offset)
									decodePC <- DEPC{PC_COMMAND:PC_NEXT, PC_IMMEDIATE: 0, PC_OFFSET: 0, PC_BUFFERS: 0}
								}
						}

					case LW:
						fmt.Println("[DECODE] tag LW")
						offset = (var_instruction & 0xFFFF)
						rt = (var_instruction & 0x1F0000)>>16
						base = (var_instruction & 0x3E00000)>>21

						if var_decode == YES{
							stateNextDecode = STATE_OTHERS
							cp0bds = 0
							fmt.Println("[DECODE] stateDecode = YES")
						} else{
							cp0bds = 1
						}

						dumpwave.Wave(1,"req_ack_DECO")
						dumpwave.Wave(WAIT_EXCEPTION,"cha_DECO")
						fmt.Println("[DECODE] DECO --> COPO (cmd: WAIT_EXCEPTION)")
						decodeCop0 <-DECO{CP0_COMMAND: WAIT_EXCEPTION, CP0_BDS: cp0bds}
						dumpwave.Wave(0,"req_ack_DECO")
						

						dumpwave.Wave(1,"req_ack_DEAL")
						dumpwave.Wave(LW,"cha_DEAL")
						fmt.Printf("[DECODE] DEAL --> ALU (cmd: LW, immediate: %d)\n",offset)
						decodeAlu <- DEAL{CMD: LW, IMMEDIATE: offset}
						dumpwave.Wave(0,"req_ack_DEAL")
						

						dumpwave.Wave(1,"req_ack_DERE")
						dumpwave.Wave(RRS_RRT,"cha_DERE")
						fmt.Printf("[DECODE] DERE --> REGISTER (cmd: RRS_WRT, rs: 0x%x, rt: 0x%x, rd: 0x%x)\n",base,rt,offset)
						decodeRegister <- DERE{RF_COMMAND:RRS_WRT, RS:base, RT:rt, RD:0}
						dumpwave.Wave(0,"req_ack_DERE")
						

						dumpwave.Wave(1,"req_ack_DEDM")
						dumpwave.Wave(RRS_RRT,"cha_DEDM")
						fmt.Println("[DECODE] DEDM --> DMUX (cmd: RRS_WRT, unit: ALU)")
						decodeDmux <- DEDM{DMUX_COMMAND:RRS_WRT, DMUX_UNIT:ALU}
						dumpwave.Wave(0,"req_ack_DEDM")
						

						dumpwave.Wave(1,"req_ack_DEMU")
						dumpwave.Wave(RRS_RRT,"cha_DEMU")
						fmt.Println("[DECODE] DEMU --> MUX (cmd: RRS_WRT, unit: ALU)")
						decodeMux <- DEMU{MUX_COMMAND:RRS_WRT, MUX_UNIT:ALU}
						dumpwave.Wave(0,"req_ack_DEMU")

						if var_decode == YES{
							dumpwave.Wave(1,"req_ack_DEPC")
							fmt.Printf("[DECODE] DEPC --> PC (cmd: PC_NEXT, immediate: 0, offset: 0 buffers: 0)\n")
							decodePC <- DEPC{PC_COMMAND:PC_NEXT, PC_IMMEDIATE: 0, PC_OFFSET: 0, PC_BUFFERS: 0}
							dumpwave.Wave(PC_NEXT,"cha_DEPC")
							dumpwave.Wave(0,"req_ack_DEPC")
						}
		
					case SW:
						fmt.Println("[DECODE] tag SW")
						offset = (var_instruction & 0xFFFF)
						rt = (var_instruction & 0x1F0000)>>16
						base = (var_instruction & 0x3E00000)>>21

						if var_decode == YES{
							stateNextDecode = STATE_OTHERS
							fmt.Printf("[DECODE] DEPC --> PC (cmd: PC_NEXT, immediate: 0x%x, offset: 0x%x buffers: 0)\n",instr_index,offset)
							decodePC <- DEPC{PC_COMMAND:PC_NEXT, PC_IMMEDIATE: 0, PC_OFFSET: 0, PC_BUFFERS: 0}
							cp0bds = 0
							fmt.Println("[DECODE] stateDecode = YES")
						} else{
							cp0bds = 1
						}

						fmt.Println("[DECODE] DECO --> COPO (cmd: WAIT_EXCEPTION)")
						decodeCop0 <-DECO{CP0_COMMAND: WAIT_EXCEPTION, CP0_BDS: cp0bds}

						fmt.Printf("[DECODE] DEAL --> ALU (cmd: SW, immediate: %d)\n",offset)
						decodeAlu <- DEAL{CMD: SW, IMMEDIATE: offset}

						fmt.Printf("[DECODE] DERE --> REGISTER (cmd: RRS_RRT, rs: 0x%x rt: 0x%x, rd: 0x%x)\n",base,rt,offset)
						decodeRegister <- DERE{RF_COMMAND:RRS_RRT, RS:base, RT:rt, RD:0}

						fmt.Println("[DECODE] DEDM --> DMUX (cmd: RRS_RRT, unit: ALU)")
						decodeDmux <- DEDM{DMUX_COMMAND:RRS_RRT, DMUX_UNIT:ALU}

					case J:
						fmt.Println("[DECODE] tag J")
						if var_decode == YES{
							fmt.Println("[DECODE] var_decode = YES")

							fmt.Println("[DECODE] stateNextDecode = STATE_NULLIFY_SECOND")
							stateNextDecode = STATE_NULLIFY_SECOND

							instr_index = (var_instruction & 0x3FFFFFF)
							offset = (var_instruction & 0xFF)

							fmt.Println("[DECODE] DECO --> COPO (cmd: NOTHING, cp0bds: 1)")
							decodeCop0 <- DECO{CP0_COMMAND: NOTHING, CP0_BDS: 1}

							fmt.Printf("[DECODE] DEPC --> PC (cmd: PC_IMMEDIATE_JUMP, immediate: 0x%x, offset: 0x%x, buffers: 0)\n",instr_index,offset)
							decodePC <- DEPC{PC_COMMAND: PC_IMMEDIATE_JUMP, PC_IMMEDIATE: instr_index, PC_OFFSET: offset, PC_BUFFERS: 0}
						}

					case BEQ:
						fmt.Println("[DECODE] tag BEQ")
						if var_decode == YES{
							fmt.Println("[DECODE] var_decode = YES")
							offset = (var_instruction & 0xFFFF)
							rt = (var_instruction & 0x1F0000)>>16
							rs = (var_instruction & 0x3E00000)>>21

							fmt.Println("[DECODE] stateNextDecode = STATE_BRANCH_SENT")
							stateNextDecode = STATE_BRANCH_SENT

							fmt.Println("[DECODE] DECO --> COP0 (cmd: NOTHING, cp0bds: 1)")
							decodeCop0 <-DECO{CP0_COMMAND: NOTHING, CP0_BDS: 1}

							fmt.Printf("[DECODE] DERE --> REGISTER (cmd: RRS_RRT, rs: 0x%x, rt: 0x%x, rd: 0)\n",rs,rt)
							decodeRegister <- DERE{RF_COMMAND:RRS_RRT, RS:rs, RT:rt, RD:0}

							fmt.Println("[DECODE] DEDM --> DMUX (cmd: RRS_RRT, unit: ALU)")
							decodeDmux <- DEDM{DMUX_COMMAND:RRS_RRT, DMUX_UNIT:ALU}

							fmt.Println("[DECODE] DEAL --> ALU (cmd: BEQ, immediate: 0)")
							decodeAlu <-DEAL{CMD: BEQ, IMMEDIATE: offset}
							
							fmt.Printf("[DECODE] DEPC --> PC (cmd: PC_NEXT, immediate: 0, offset: %d, buffers: 0)\n",offset)
							decodePC <- DEPC{PC_COMMAND: PC_NEXT, PC_IMMEDIATE: 0, PC_OFFSET: offset, PC_BUFFERS: 0}
						}
				}
			}
		}
	}
}
